﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Web;

namespace SchemaMonitor
{
    //Signatures
    public delegate void DLogErr(Exception ex, CUser user, string msg);
    public delegate void DLogMsg(CUser user, params object[] p);

    //Logging Helper
    public class CLog
    {
        //Constructors
        public CLog() : this(null) { }
        public CLog(CUser user) : this(user, null, null) { }
        public CLog(CUser user, DLogErr err, DLogMsg msg)
        {
            _user = user;
            _err = err?? new DLogErr(CLog.LogErr);
            _msg = msg?? new DLogMsg(CLog.LogMsg);
        }
 
        //Members
        private CUser _user;
        private DLogMsg _msg;
        private DLogErr _err;

        //Public
        public CUser User {  get { return _user; } }
        public void Log(params object[] p)
        {
            if (null != _msg)
                _msg(_user, p);
        }
        public void Log(Exception ex, string msg = null)
        {
            if (null != _msg)
                _err(ex, _user, msg);
        }

        #region Static
        //Public
        public static void LogEx(CUser u, params object[] p) { LogErr(new Exception(string.Concat(p)), u); }
        public static void LogEx(CUser u, string s) { LogErr(new Exception(s), u); }
        public static void Log(Exception ex, CUser u, string msg = null) { LogErr(ex, u, msg); }
        public static void Log(string s) { LogMsg(s); }
        public static void Log_(params object[] p) { LogMsg(string.Concat(p)); }

        //Private
        private static void LogMsg(string s)
        {
			if (null == HttpContext.Current)
				Console.WriteLine(s);
			else
			{
				HttpContext.Current.Response.Write(s + "\r\n");	// HttpUtility.HtmlEncode(s + "\r\n").Replace("\r\n", "<br/>"));
				HttpContext.Current.Response.Flush();
			}
		}
		private static void LogMsg(CUser user, params object[] p)
        {
            LogMsg(user, string.Concat(p));
        }
        private static void LogMsg(CUser user, string s)
        {
            if (null == user)
                LogMsg(s);
            else
                LogMsg(string.Concat(user.UserName, ": ", s));
        }

        //Errors
        private static void LogErr(Exception ex, CUser user, string msg = null)
        {
            //Ex+Msg
            string s = ex.Message;
            if (null != msg)
                s = string.Concat(msg, "\r\n" , s);

            //Console
            LogMsg(user, s);

            //Database
            CError e = new CError();
            e.ErrorHash = ex.ToString().GetHashCode();
            e.ErrorMessage = s;
            e.ErrorStacktrace = ex.StackTrace ?? string.Empty;
            if (null != ex.InnerException)
            {
                e.ErrorInnerMessage = ex.InnerException.Message;
                e.ErrorInnerStacktrace = ex.InnerException.StackTrace;
            }
            e.ErrorUserId = user.UserId;
            e.ErrorUserName = user.UserName;
            e.ErrorRawUrl = "Monitor.exe";
            e.ErrorQuerystring = string.Empty;
            try
            {
                e.Save();
            }
            catch
            {
                LogToFile(ex.Message);
            }
        }

        //Errors - FAilOver to Filesystem
        private static void LogToFile(params object[] msg) { LogToFile(string.Concat(msg)); }
        private static void LogToFile(string msg)
        {
			msg = string.Concat(DateTime.Now, "\t", msg, "\r\n");
			if (null == HttpContext.Current)
				File.AppendAllText(CConfig.LogPath, msg);
			else
			{
				HttpContext.Current.Response.Write(msg);// HttpUtility.HtmlEncode(msg).Replace("\r\n", "<br/>"));
				HttpContext.Current.Response.Flush();
			}
		}

        //Config
        private class CConfig : SchemaMonitor.CConfig
        {
            public static string LogPath { get { return Config("LogPath", "log.txt"); } }
        }
        #endregion
    }
}
